package com.zhku.zhny.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

public class POIUtil {
	
	public static <T> boolean exportDataToExcel(OutputStream out, List<T> data, String themeName, String[] headNames)
			throws Exception {
		Workbook wb = new HSSFWorkbook();
		Sheet sheet = wb.createSheet(themeName);
		Row theme = sheet.createRow(0);
		Cell cell = theme.createCell(0);
		cell.setCellValue(themeName);
		sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, headNames.length));

		CellStyle cellStyle = wb.createCellStyle();
		// 设置居中对齐
		cellStyle.setAlignment(HorizontalAlignment.CENTER);
		cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
		// 设置表头
		Row rowHeader = sheet.createRow(1);
		for (short i = 0; i < headNames.length; i++) {
			rowHeader.createCell(i).setCellValue(headNames[i]);
		}
		Iterator<T> it = data.iterator();
		int index = 2;
		int rowNum = 1;
		// 遍历集合数据，从第三行开始填入数据行
		while (it.hasNext()) {
			Row row = sheet.createRow(index++);
			T bean = it.next();
			// 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
			Field[] fields = bean.getClass().getDeclaredFields();
			for (short i = 0; i < fields.length; i++) {
				Cell oneCell = row.createCell(i);
				if (i == 0) {
					oneCell.setCellValue(rowNum);
					rowNum++;
					continue;
				}
				Field field = fields[i];
				if (field.toString().contains("static")) {
					continue;
				}
				String fieldName = field.getName();
				String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
				Class<? extends Object> beanClass = bean.getClass();
				Method method = beanClass.getDeclaredMethod(getMethodName, new Class[] {});
				Object value = method.invoke(bean, new Object[] {});
				String textValue = null;
				// 判断值的类型后进行强制类型转换
				if (value instanceof Date) {
					Date date = (Date) value;
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
					textValue = sdf.format(date);
				} else {
					// 其它数据类型都当作字符串简单处理
					if (value == null) {
						value = "";
					}
					textValue = value.toString();
				}
				oneCell.setCellValue(textValue);
			}
		}
		wb.write(out);
		wb.close();
		return false;
	}

	public static boolean exportDataToWord(String templeUrl, OutputStream out, Map<String, String> infoMap)
			throws Exception {
		// 获取docx文档对象
		InputStream is = new FileInputStream(new File(templeUrl));
		XWPFDocument document = new XWPFDocument(is);
		changeTable(document, infoMap); // 解析替换表格对象
		// 写入输出流
		document.write(out);
		is.close();
		document.close();
		return true;
	}

	private static void changeTable(XWPFDocument document, Map<String, String> infoMap) {
		// 获取表格对象集合
		List<XWPFTable> tables = document.getTables();
		// 获取表格
		XWPFTable table = tables.get(0);
		// 获取表格行集合
		List<XWPFTableRow> rows = table.getRows();
		// 遍历表格，并替换模板
		for (XWPFTableRow row : rows) {
			// 获取每一行的列集合
			List<XWPFTableCell> cells = row.getTableCells();
			for (XWPFTableCell cell : cells) {
				// 判断单元格是否需要替换
				if (checkText(cell.getText())) {
					// 获取文本段落
					List<XWPFParagraph> paragraphs = cell.getParagraphs();
					for (XWPFParagraph paragraph : paragraphs) {
						if (!checkText(paragraph.getParagraphText())) {
							continue;
						}
						replaceInPara(paragraph, infoMap); // 替换段落里的变量
					}
				}
			}
		}
	}

	public static void replaceInPara(XWPFParagraph paragraph, Map<String, String> infoMap) {
		List<XWPFRun> runs = paragraph.getRuns();
		for (int i = 0; i < runs.size(); i++) {
			XWPFRun run = runs.get(i);
			String runText = run.toString().trim();
			if ('$' == runText.charAt(0) && '{' == runText.charAt(1) && '}' == runText.charAt(runText.length() - 1)) {
				paragraph.removeRun(i);
				for (String key : infoMap.keySet()) {
					if (runText.equals(key)) {
						XWPFRun newRun = paragraph.createRun();
						setRunStyle(newRun);
						newRun.setText(infoMap.get(key));
						break;
					}
				}
			}
		}
	}

	public static boolean checkText(String text) {
		boolean bool = false;
		if (text.indexOf("$") != -1) {
			bool = true;
		}
		return bool;
	}

	public static void setRunStyle(XWPFRun run) {
		run.setFontSize(14); // 设置四号字体
	}
}
